<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class User {

    public $id = null;
    public $name = null;
    public $allianceId = null;
    public $allianceName = null;
    public $sampleUrl = null;
    public $baseUrl = null;
    public $token = null;
    public $db = null;
    public $downloader = null;

    public function __construct() {
        $CI = &get_instance();
        $CI->load->library('downloader');
        $this->db = &$CI->db;
        $this->downloader = &$CI->downloader;
    }

    public function parseUrl($url) {
        $url = urldecode($url);

        $this->sampleUrl = $url;
        $this->baseUrl = strstr($url, '/players/', true);
        $this->token = substr(strstr($url, '?'), 1);

        // get user_id
        $matches = array();
        $result = preg_match('/user_id=([0-9]+)/i', $this->token, $matches);

        if (count($matches) > 1) {
            $this->id = $matches[1];
            $this->updateCurrentPlayer();
        }

        return ($this->id !== null) &&
        ($this->sampleUrl != '') &&
        ($this->baseUrl != '') &&
        ($this->token != '');
    }

    public function toArray() {
        return Array(
            'id' => $this->id,
            'name' => $this->name,
            'allianceId' => $this->allianceId,
            'allianceName' => $this->allianceName,
            'sampleUrl' => $this->sampleUrl,
            'baseUrl' => $this->baseUrl,
            'token' => $this->token,
        );
    }

    public function updateCurrentPlayer() {
        $CI = &get_instance();
        $baseUrl = $this->baseUrl;
        $token = $this->token;
        $url = "$baseUrl/player?$token";
        try {
            $result = $this->downloader->request($url);
            //$CI->cache->save('current_player_data', $result, 60*30);//cache 30 min
            //$result = $CI->cache->get('current_player_data');

            $result = json_decode($result);
            //var_dump($result);die;
            $response = $result->response;

            $data = array(
                'id' => $response->id,
                'name' => $response->name,
                'level' => $response->level,
                'alliance_id' => isset($response->alliance) ? $response->alliance->id : '',
                'alliance_name' => isset($response->alliance) ? $response->alliance->name : '',
                'damage_protection' => ($response->damage_protection) ? 1 : 0,
                'online' => ($response->is_playing) ? 1 : 0,
                'res1' => $response->base->resources->crystal,
                'res2' => $response->base->resources->gas,
                'res3' => $response->base->resources->energy,
                'res4' => $response->base->resources->uranium,
                'updated_time' => date('Y-m-d H:i:s'), //date('Y-m-d H:i:s', $response->timestamp),
            );

            //update db
            $id = $this->id;
            $name = $CI->db->escape_str($data['name']);
            $allianceId = $data['alliance_id'];
            $ip = $_SERVER['REMOTE_ADDR'];
            
            $token = $CI->db->escape_str($token);

            $sql = "INSERT INTO user (id, name, alliance_id, ip, last_access_time, token) VALUES ($id,'$name','$allianceId', '$ip', NOW(), '$token')
                ON DUPLICATE KEY UPDATE name='$name', alliance_id='$allianceId', ip='$ip', last_access_time=NOW(), token='$token'";

            $query = $CI->db->query($sql);

            //update this
            $this->id = $id;
            $this->name = $name;
            $this->allianceId = $allianceId;

            return $data;
        } catch (Exception $e) {
            return false;
        }
    }

    public function requestPlayer($id) {
        $baseUrl = $this->baseUrl;
        $token = $this->token;
        $url = "$baseUrl/players/$id?$token";

        try {
            $result = $this->downloader->request($url);
            $result = json_decode(base64_decode($result));
            $response = $result->response;

            $base = $response->base;
            $attack_boost = $base->permanent_attack?1:0;
            $hp_boost = $base->permanent_armor?1:0;
            $last_login = date('Y-m-d H:i:s', $response->last_login);

            $building_hp = 0;
			$cc_level = 0;
            foreach ($base->buildings as $item) {
                $building_hp += $item->hp;
				if ($item->type == 'CommandCenter')
					$cc_level = $item->level;
            }

            $data = array(
                'id' => $response->id,
                'name' => $response->name,
                'level' => $response->level,
                'alliance_id' => isset($response->alliance) ? $response->alliance->id : '',
                'alliance_name' => isset($response->alliance) ? $response->alliance->name : '',
                'damage_protection' => ($response->damage_protection) ? 1 : 0,
                'online' => ($response->is_playing) ? 1 : 0,
                'res1' => $response->base->resources->crystal,
                'res2' => $response->base->resources->gas,
                'res3' => $response->base->resources->energy,
                'res4' => $response->base->resources->uranium,
                'attack_boost' => $attack_boost,
                'hp_boost' => $hp_boost,
                'building_hp' => $building_hp,
                'last_login' => $last_login,
                'cc_level' => $cc_level,
                'updated_time' => date('Y-m-d H:i:s'), //date('Y-m-d H:i:s', $response->timestamp),
            );
            return $data;
        } catch (Exception $e) {
            return false;
        }
    }

    public function getWorldPlayers() {
        $baseUrl = $this->baseUrl;
        $token = $this->token;
        $url = "$baseUrl/players/search_all_player_opponents?$token";

        $result = $this->downloader->request($url);
        $resultJson = json_decode($result);
        $response = $resultJson->response;
        $searchResult = $response->search_results;
        //echo(count($searchResult));
        $idArray = array();
        foreach ($searchResult as $item) {
            $idArray[] = $item->opponent->id;
        }
        return implode(',', $idArray);
    }

    public function getOpponentPlayers() {
        $baseUrl = $this->baseUrl;
        $token = $this->token;
        $url = "$baseUrl/players/search_feuds?$token";

        $result = $this->downloader->request($url);
        $resultJson = json_decode($result);
        $response = $resultJson->response;
        $searchResult = $response->search_results;
        //echo(count($searchResult));
        $idArray = array();
        foreach ($searchResult as $item) {
            $idArray[] = $item->opponent->id;
        }
        return implode(',', $idArray);
    }

    public function getTeamPlayers() {
        //get new data
        $CI = &get_instance();
        $edgeWorld = $CI->config->item('edgeworld');
        $teamId = $edgeWorld['team_id'];

        $teamData = $this->getAlliance($teamId);  
        $members = $teamData->members;
        //echo(count($searchResult));
        $idArray = array();
        foreach ($members as $item) {
            $idArray[] = $item->id;
        }
        return implode(',', $idArray);
    }

    public function updatePlayer($id, $src) {
        $CI = &get_instance();

        $data = $this->requestPlayer($id);

        $id = $data['id'];
        $name = $CI->db->escape_str($data['name']);
        $level = $data['level'];
        $alliance_id = $data['alliance_id'];
        $alliance_name = $CI->db->escape_str($data['alliance_name']);
        $damage_protection = $data['damage_protection'];
        $online = $data['online'];
        $res1 = $data['res1'];
        $res2 = $data['res2'];
        $res3 = $data['res3'];
        $res4 = $data['res4'];
        
        $attack_boost   = $data['attack_boost'];
        $hp_boost       = $data['hp_boost'];
        $building_hp    = $data['building_hp'];
        $last_login     = $data['last_login'];
		$cc_level		= $data['cc_level'];

        $updated_time = $data['updated_time'];
        $source = $CI->db->escape_str($src);
        $user_id = $this->id;

        $sql = "INSERT INTO 
            `player` (`id`, `name`, `level`,`alliance_id`, `alliance_name`, `damage_protection`, `online`, `res1`, `res2`, `res3`, `res4`, `updated_time`, `source`, user_id, attack_boost, hp_boost, building_hp, last_login,cc_level) 
            VALUES ($id,'$name',$level,'$alliance_id','$alliance_name','$damage_protection','$online',$res1,$res2,$res3,$res4,'$updated_time','$src', $user_id, $attack_boost, $hp_boost, $building_hp, '$last_login',$cc_level)
            ON DUPLICATE KEY UPDATE
                name='$name',level=$level,`alliance_id`='$alliance_id', alliance_name='$alliance_name',damage_protection='$damage_protection',online='$online',res1=$res1,res2=$res2,res3=$res3,res4=$res4,updated_time='$updated_time',source='$src',user_id=$user_id, attack_boost=$attack_boost, hp_boost=$hp_boost, building_hp=$building_hp, last_login='$last_login',cc_level=$cc_level";
        //echo $sql;die;
        $CI->db->query($sql);
		
		
        $data['last_update'] = '00:00:00';
        //var_dump($updated_time);die;
        //var_dump(date('H:i:s',time()));die;
        return $data;
    }

    public function browseData($minRes = 10000000, $notDamageProtection=true, $offline=true, $notFriend=true, $timeLimit=null, $excludeAllianceId=null, $sortBy='level') {
        $CI = &get_instance();
        if ($this->id == null) {
            return null;
        }

        $userId = $this->id;
        $minResCriteria = ($minRes>0) ? " AND (res1>$minRes OR res2>$minRes OR res3>$minRes OR res4>$minRes)" : '';
        $onlineCriteria = ($offline) ? ' AND online=0' : '';
        $damageCriteria = ($notDamageProtection) ? ' AND damage_protection=0' : '';
        $friendCriteria = ($notFriend) ? ' AND friend_status!=1' : '';
        $excludeAllianceCriteria = ($excludeAllianceId!==null)?" AND player.alliance_id!=$excludeAllianceId":'';

        $timeCriteria = '';
        switch ($timeLimit) {
            case '30':
                $timeCriteria = " AND player.updated_time>'" . date('Y-m-d H:i:s', strtotime('-30 minutes')) . "'";
                break;
            case '60':
                $timeCriteria = " AND player.updated_time>'" . date('Y-m-d H:i:s', strtotime('-60 minutes')) . "'";
                break;
        }
        
        switch ($sortBy) {
            case 'res1': $orderBy = 'res1 DESC';break;
            case 'res2': $orderBy = 'res2 DESC';break;
            case 'res3': $orderBy = 'res3 DESC';break;
            case 'res4': $orderBy = 'res4 DESC';break;
            case 'hp': $orderBy = 'building_hp DESC';break;
            default: 
                $orderBy = 'level';
        }


        $sql = "SELECT player.*, timediff(now(),player.updated_time) as last_update FROM player 
                INNER JOIN user ON player.user_id=user.id                 
            WHERE user.id=$userId 
                $onlineCriteria $damageCriteria $friendCriteria $timeCriteria $minResCriteria $excludeAllianceCriteria     
            ORDER BY $orderBy";

        
        $query = $CI->db->query($sql);

        return $query->result_array();
    }

    public function getAlliance($id) {
        $baseUrl = $this->baseUrl;
        $token = $this->token;
        $url = "$baseUrl/alliances/$id?$token";

        $result = $this->downloader->request($url);
        
        return json_decode($result)->response;
    }

    public function getAttackerAlliance() {
        $CI = &get_instance();
        if ($this->id == null) {
            return null;
        }
        $userId = $this->id;

        // get alliance id
        $id = $this->allianceId;
        $allianceData = $this->getAlliance($id);
        $members = $allianceData->members;

        $alliance = Array();

        foreach ($members as $m) {
            //var_dump($m->last_attack);
            if (property_exists($m->last_attack, 'attacker')) {
            $attacker = $m->last_attack->attacker;
            $id = isset($attacker->alliance_id) ? $attacker->alliance_id : null;
            $name = isset($attacker->alliance_name) ? $attacker->alliance_name : null;

            if ($id !== null && (!isset($alliance[$id]) || $alliance[$id]['ref_level'] < $m->level)) {
                $alliance[$id]['name'] = $name;
                $alliance[$id]['ref_member_id'] = $attacker->id;
                $alliance[$id]['ref_member_name'] = $attacker->name;
                $alliance[$id]['ref_level'] = $m->level;
                $alliance[$id]['source'] = $attacker->name . " attacks " . $m->name . " lv " . $m->level;
            }
            }
        }

        $keys = array_keys($alliance);
        $return = array();
        foreach ($keys as $k) {
            $id = $k;
            $name = $this->db->escape_str($alliance[$k]['name']);
            $ref_member_id = $alliance[$k]['ref_member_id'];
            $ref_member_name = $this->db->escape_str($alliance[$k]['ref_member_name']);
            $source = $this->db->escape_str($alliance[$k]['source']);

            $sql = "INSERT INTO alliance (id,name,ref_member_id,ref_member_name,updated_time,source) VALUES
                ($id,'$name',$ref_member_id,'$ref_member_name',NOW(),'$source') 
                ON DUPLICATE KEY UPDATE 
                name='$name',ref_member_id=$ref_member_id,ref_member_name='$ref_member_name',updated_time=NOW(),source='$source'";

            $this->db->query($sql);
        }

        //update friend status
        $allianceData = $this->getAlliance($this->allianceId);
        $friendList = implode(',', $allianceData->friend_ids) . ',-1';
        $sql = "UPDATE player SET friend_status=1 WHERE alliance_id in ($friendList) AND user_id=" . $this->id;
        $this->db->query($sql);

        return $alliance;
    }

    public function updateAlliance($data) {
        //update friend status
        /*
          $friendList = ','.implode(',',$data->friend_ids).',';
          $foeList    = ','.implode(',',$data->foe_ids).',';

          $id = $data->alliance->id;
          $current = ','.$this->allianceId.',';
          if (strpos($friendList, $current)!==false)
          $friendStatus = 1;
          elseif (strpos($foeList, $current)!==false)
          $friendStatus = 2;
          else
          $friendStatus = 0;

          $sql = "UPDATE player SET friend_status=$friendStatus WHERE alliance_id=$id AND user_id=".$this->id;
          $this->db->query($sql);/* */
    }

    public function findPlayerByName($name) {
        
    }

    public function updateMessages($token) {
        $CI = &get_instance();
        $url = "http://sector14.c1.galactic.wonderhill.com/api/player/messages?$token";
        //$result = $this->downloader->request($url);  
        //$CI->cache->save('msg', $result, 60*30);//cache 30 min
        $result = $CI->cache->get('msg');
        $messages = json_decode($result)->response->messages;

        $msgs = array();
        foreach ($messages as $m) {
            $id = $m->id;
            $created_time = date('Y-m-d H:i:s', $m->created_at);
            $type = $m->type;
            $sender = '';

            switch ($type) {
                case 'gift_note':
                    $sender = $m->sender;
                    break;
                case 'alliance_broadcast':
                    break;
                default:
                    if (isset($m->sender) && isset($m->sender->name))
                        $sender = $m->sender->name;break;
            }

            $sender = $this->db->escape_str($sender);
            $subject = (isset($m->subject)) ? $this->db->escape_str($m->subject) : '';
            $body = (isset($m->body)) ? $this->db->escape_str($m->body) : '';

            $msgs[] = array(
                'id' => $id,
                'created_time' => $created_time,
                'type' => $type,
                'sender' => $sender,
                'subject' => $subject,
                'body' => $body,
            );

            $sql = "INSERT IGNORE INTO msg (id, created_time, type, sender, subject, body) VALUES ($id, '$created_time', '$type', '$sender', '$subject', '$body')";
            $query = $this->db->query($sql);
        }

        return $msgs;
    }

    public function updateBankHistory($token) {
        $CI = &get_instance();
        $url = "http://sector14.c1.galactic.wonderhill.com/api/player/messages?$token";
        $result = $this->downloader->request($url);
        //$CI->cache->save('msg', $result, 60*30);//cache 30 min
        //$result = $CI->cache->get('msg');
        $messages = json_decode($result)->response->messages;

        $msgs = array();
        foreach ($messages as $m) {
            $type = $m->type;
            $sender = '';

            if ($m->type == 'gift_note') {
                $id = $m->id;
                $created_time = date('Y-m-d H:i:s', $m->created_at);
                $sender = $m->sender;
                $body = $m->body;

                $matches = array();
                $result = preg_match_all('/([0-9,]+)\s(crystal|gas|energy|uranium)/', $m->body, $matches);

                if ($result !== false) {
                    $res1 = 0;
                    $res2 = 0;
                    $res3 = 0;
                    $res4 = 0;

                    for ($i = 0; $i < 3; $i++) {
                        if (isset($matches[1][$i])) {
                            $res = str_replace(',', '', $matches[1][$i]);
                            switch ($matches[2][$i]) {
                                case 'crystal': $res1 = $res;
                                    break;
                                case 'gas': $res2 = $res;
                                    break;
                                case 'energy': $res3 = $res;
                                    break;
                                case 'uranimum': $res4 = $res;
                                    break;
                            }
                        }
                    }

                    $sender = $this->db->escape_str($sender);
                    $player_id = 'null';
                    $body = $this->db->escape_str($body);
                    $sql = "INSERT IGNORE INTO player_bank (msg_id, player_id, player_name, created_time, res1, res2, res3, res4, msg_body) 
                        VALUES ($id, $player_id, '$sender', '$created_time', $res1, $res2, $res3, $res4, '$body')";

                    $query = $this->db->query($sql);
                }
            }
        }

        return $msgs;
    }

    public function updateTeam() {
        //get old data
        $sql = 'SELECT * FROM player_history';
        $query = $this->db->query($sql);
        $result = $query->result_array();
        $oldData = Array();
        foreach ($result as $m) {
            $oldData[$m['player_id']] = $m;
        }

        //get new data
        $CI = &get_instance();
        $edgeWorld = $CI->config->item('edgeworld');
        $teamId = $edgeWorld['team_id'];

        $teamData = $this->getAlliance($teamId);        
        
        $members = $teamData->members;

        $newData = array();
        $idList = array();
        foreach ($members as $m) {


            $player_id = $m->id;
            $idList[] = $player_id;

            $name = $this->db->escape_str($m->name);
            $alliance_id = isset($response->alliance) ? $response->alliance->id : '';
            $level = $m->level;
            $last_update = date('Y-m-d H:i:s', $teamData->timestamp);
            $last_activity = '';
            $last_activity_time = NULL;

            $sql = "INSERT IGNORE INTO player_history (player_id, alliance_id, name, level, last_update, last_activity, last_activity_time) VALUES
                ($player_id, '$alliance_id', '$name', $level, '$last_update', NULL, NULL)";

            if (isset($oldData[$m->id])) {
                if ($m->level != $oldData[$m->id]['level']) {
                    $last_activity = 'level up';
                    $last_activity_time = $last_update;
                    $sql = "UPDATE player_history SET name='$name', level=$level, last_update='$last_update', last_activity = '$last_activity', last_activity_time='$last_activity_time' WHERE player_id=$player_id";
                }
            }

            $query = $this->db->query($sql);
            //var_dump($sql);
        }

        //clear old players not in team
        $idList = implode(',', $idList);
        if ($idList == '')
            $idList = '(-1)';
        $sql = "DELETE FROM player_history WHERE player_id NOT IN ($idList)";
        $query = $this->db->query($sql);

        //update bank
        $id = $edgeWorld['bank_id'];
        $p = $this->requestPlayer($id);
        $bankData = json_encode(array(
            'res1' => $p['res1'],
            'res2' => $p['res2'],
            'res3' => $p['res3'],
            'res4' => $p['res4'],
                ));

        $sql = "INSERT INTO config (name, value) VALUES ('bank_data', '$bankData') ON DUPLICATE KEY UPDATE value='$bankData'";
        $query = $this->db->query($sql);
        //var_dump($newData);
        //var_dump($oldData);
    }

    public function getMessages() {
        $sql = "SELECT * FROM msg ORDER BY id DESC";
        $query = $this->db->query($sql);

        return $query->result_array();
    }

    public function getPlayerHistory($sort = 'level') {
        //get bank activities
        $sql = "DROP TABLE IF EXISTS tmp_player_bank";
        $query = $this->db->query($sql);

        $time = date('Y-m-d H:i:s', strtotime("-7 days"));
        $sql = "CREATE TABLE tmp_player_bank AS SELECT player_name,sum(res1+res2+res3+res4) AS deposit FROM player_bank WHERE created_time>'$time' GROUP BY player_name ";
        $query = $this->db->query($sql);


        switch ($sort) {
            case 'deposit':
                $sortCriterial = 'ORDER BY deposit DESC';
                break;
            case 'activity':
                $sortCriterial = 'ORDER BY last_activity_time DESC';
                break;
            default:
                $sortCriterial = 'ORDER BY level DESC';
        }
        $sql = "SELECT * FROM player_history H LEFT JOIN tmp_player_bank B ON H.name=B.player_name $sortCriterial";
        //echo $sql;
        $query = $this->db->query($sql);

        $data = $query->result_array();
        return $data;
    }

    public function getDbConfig() {
        $sql = 'SELECT * FROM config';
        $query = $this->db->query($sql);
        $data = array();
        foreach ($query->result_array() as $row) {
            $data[$row['name']] = $row['value'];
        }
        return $data;
    }

}

/* End of file Someclass.php */